import { Camera } from "@babylonjs/core/Cameras/camera";
import { Light } from "@babylonjs/core/Lights/light";
import { Scene } from "@babylonjs/core/scene";
import { Stage } from "./stage";
import { ActiveDefaultVRExperience, IActiveDefaultVRExperienceOptions, IVRContainer } from "../xr/vr-container";
import { CaptureScreen } from '../highly-coupled-component/capture-screen';
import { ControllerTip } from '../xr/xr-input/controller-tip';
import { CameraInputPreset } from '../preset/camera-input-preset';
import { Helper } from "../tool/helper";
import { SwitchView } from "../highly-coupled-component/switch-view";
import { ActiveDefaultARExperience, IARContainer, IActiveDefaultARExperienceOptions } from '../xr/ar-container';


/**
 * xr特有的舞台（目前仅支持vr）
 */
abstract class XRStage extends Stage {

    /**
     * vr容器对象
     */
    public vr: IVRContainer | null = null;

    /**
     * ar容器对象
     */
    public ar: IARContainer | null = null;

    /**
     * 渲染函数（默认仅渲染主场景）
     */
    public render(): void {
        this.mainScene.render();
    }

    /**
     * 主相机（默认为xr容器活动相机或场景活动相机）
     */
    public get mainCamera(): Camera {
        return this.vr ? this.vr.camera : (this.ar ? this.ar.camera : this.camreas[0]);
    }

    /**
     * 会话模式immersive-vr/immersive-ar
     */
    protected get sessionMode(): 'immersive-vr' | 'immersive-ar' {
        return 'immersive-vr';
    }

    /**
     * 空间类型
     */
    protected get referenceSpaceType(): 'local' | 'local-floor' | 'bounded-floor' | 'unbounded' | 'viewer' {
        return 'local-floor';
    }

    /**
     * xr相关参数
     */
    protected abstract getXROptions(): IActiveDefaultVRExperienceOptions | IActiveDefaultARExperienceOptions;

    /**
     * 是否生产环境
     */
    protected abstract isProduction(): boolean;

    /**
     * 工程名称
     */
    protected abstract appName(): string;

    /**
     * 切换沉浸模式（默认仅处理沉浸模式）
     * @param inaction 无动作（不进行沉浸模式的切换，执行继承后自定义的逻辑）
     */
    public async changeImmersive(inaction?: boolean): Promise<void> {
        if (inaction) return;
        if (this.sessionMode === 'immersive-vr') {
            if (!this.vr) return;
            if (Helper.isImmersive(this.mainScene)) {
                await this.vr.helper.exitXRAsync();
            } else {
                await this.vr.helper.enterXRAsync('immersive-vr', this.referenceSpaceType);
            }
        } else if (this.sessionMode === 'immersive-ar') {
            if (!this.ar) return;
            if (Helper.isImmersive(this.mainScene)) {
                await this.ar.helper.exitXRAsync();
            } else {
                await this.ar.helper.enterXRAsync('immersive-ar', this.referenceSpaceType);
            }
        }
    }

    /**
     * 重置当前舞台（默认仅重置沉浸状态）
     */
    public async reset(): Promise<void> {
        if (Helper.isImmersive(this.mainScene)) {
            await this.vr!.helper.exitXRAsync();
        }
    }

    /**
     * 切换视角（默认为切换视角到背后，避免转身的动作）
     */
    public resetSight(): void {
        SwitchView.generic(this.mainScene);
    }

    /**
     * 初始化xr容器，一般情况下不需要重写此方法
     * @param scenes 场景
     * @param cameras 相机
     * @param lights 灯光
     */
    protected async initializeComponents(scenes: Scene[], cameras: Camera[], lights: Light[]): Promise<void> {
        await this.initializeXRExperience();
        this.generateComponents(scenes, cameras, lights);
    }

    /**
     * 创建自定义组件
     * @param scenes 场景
     * @param cameras 相机
     * @param lights 灯光
     */
    protected abstract generateComponents(scenes: Scene[], cameras: Camera[], lights: Light[]): void;

    /**
     * 初始化xr对象及默认配置
     */
    protected async initializeXRExperience(): Promise<void> {
        const xr = this.sessionMode === 'immersive-vr' ?
            await ActiveDefaultVRExperience(this.mainScene, this.canvas, this.getXROptions()) :
            await ActiveDefaultARExperience(this.mainScene, this.canvas, this.getXROptions());

        const immersiveChangeCommonHandle = (container: IVRContainer | IARContainer) => {
            CaptureScreen.debug = false;
            CaptureScreen.register(this.engine, this.mainCamera, this.isProduction(), this.appName());
        };
        immersiveChangeCommonHandle(xr!);
        xr!.onIn(immersiveChangeCommonHandle);
        xr!.onNotIn(immersiveChangeCommonHandle);
        ControllerTip.initialize(xr!);


        if (this.sessionMode === 'immersive-vr') {
            this.vr = xr as IVRContainer;
        } else {
            this.ar = xr as IARContainer;
        }
    }

    protected initializeInput(scenes: Scene[], cameras: Camera[]): void {
        new CameraInputPreset(this.mainScene);
    }

}


export { XRStage };